/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 2 -*- */
/**
* @file socket.cpp
* 
* Library for easy comunication through sockets.
*
* @author Miguel Ángel Vílchez López 2008 <sacra@openmatica.es> 
*
* Codigo is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 
* Codigo is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License along
* with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "socket.hpp"
#include "debug.cpp"

CMSocket::CMSocket(unsigned int port, const char* ip="localhost", unsigned int buffer=1024,bool debug=false,const char* filename=""):debug(debug,filename)
{
        this->ip=strdup(ip);
	this->port=port;
	this->buffer_size=buffer;
        //bzero((char *) &this->struct_socket, sizeof(this->struct_socket));
	this->init();
}

CMSocket::~CMSocket()
{
}

void CMSocket::init()
{
	this->debug.debug("Trying to create the socket...");
	if((this->id = socket(PF_INET,SOCK_STREAM,0))<0)
	{
		this->debug.error(strerror(errno),__FILE__,__FUNCTION__,(__LINE__));
		exit(EXIT_FAILURE);
	}
	//Initialize and config the server data structure
	memset(&this->struct_socket,0,sizeof(this->struct_socket));
	this->struct_socket.sin_family=AF_INET;//type of protocol
	this->struct_socket.sin_port=htons(this->port);//port
        inet_aton(this->ip,&this->struct_socket.sin_addr); //=> no names
	//ligar el socket a una direccion de red
	this->address_size=sizeof(this->struct_socket);
}

int CMSocket::serverTcp()
{
	this->debug.debug("Trying to bind the socket...");
	if((bind(this->id,(struct sockaddr *)&this->struct_socket,this->address_size))<0)
	{
		this->debug.error(strerror(errno),__FILE__,__FUNCTION__,(__LINE__));
		return -1;
	}
	
	this->debug.debug("Trying to waiting for new connections...");
	if((listen(this->id,0))<0)
	{
		this->debug.error(strerror(errno),__FILE__,__FUNCTION__,(__LINE__));
		return -1;
	}
        return 0;
}

int CMSocket::serverAccept()
{
        int id_accept;

	this->debug.debug("Trying to accept new connections...");
	if((id_accept=accept(this->id,(struct sockaddr *)&this->struct_socket,&this->address_size))<0)
	{
		this->debug.error(strerror(errno),__FILE__,__FUNCTION__,(__LINE__));
		return -1;
	}
	return id_accept;
}

int CMSocket::serverRead(char* data,int id_accept)
{
	char* buffer=(char*)malloc((this->buffer_size)*sizeof(char));

	this->debug.debug("Trying to receive data from socket...");
	if (recv(id_accept, buffer, this->buffer_size, 0) == -1)
	{
		this->debug.error(strerror(errno),__FILE__,__FUNCTION__,(__LINE__));
		return -1;
	}
        
        strcpy(data,buffer);
        free(buffer);
	return 0;
}

int CMSocket::serverWrite(char *data, int id_accept)
{
	this->debug.debug("Trying to send data through socket...");
	if (send(id_accept, data, strlen(data),0) == -1)
	{
		this->debug.error(strerror(errno),__FILE__,__FUNCTION__,(__LINE__));
		return 1;
	}
	return 0;
}

int CMSocket::clientTcp()
{
	this->debug.debug("Trying to connect to server through sockets...");
	if((connect(this->id,(struct sockaddr *)&this->struct_socket,this->address_size))==-1)
	{
		this->debug.error(strerror(errno),__FILE__,__FUNCTION__,(__LINE__));
		return -1;
	}
	return 0;
}

int CMSocket::clientWrite(char *data)
{
	this->debug.debug("Trying to send data through socket...");
	if (send(this->id, data, strlen(data),0) == -1) 
	{
		this->debug.error(strerror(errno),__FILE__,__FUNCTION__,(__LINE__));
		return 1;
	}
	return 0;
}

int CMSocket::clientRead(char* data)
{
	char* buffer=(char*)malloc((this->buffer_size)*sizeof(char));

	this->debug.debug("Trying to receive data from socket...");
	if (recv(this->id, buffer, this->buffer_size, 0) == -1)
	{
		this->debug.error(strerror(errno),__FILE__,__FUNCTION__,(__LINE__));
		return -1;
	}

	strcpy(data,buffer);
        free(buffer);
	return 0;
}
